﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DatabaseSimulation
{
    public class DatabaseOperation
    {
        private static int OperationIDCounter = 0;
        public int OperationID { get; private set; }
        public Transaction Transaction { get; private set; }
        public DatabaseOperationType OperationType { get; private set; }
        public int ObjectID { get; private set; }
        public int ElapsedTempWriteTime { get; private set; }
        public int ElapsedIoTime { get; private set; }
        public int ElapsedCpuTime { get; private set; }
        public int ElapsedBlockedOnTransactionTime { get; private set; }
        public int ElapsedBlockedOnTransactionTime2 { get; private set; }
        public int ElapsedBlockedOnHardDriveTime { get; private set; }
        public int ElapsedBlockedOnCpuTime { get; private set; }
        public bool TempCompleted { get; private set; }
        public bool Completed { get; private set; }

        public int IoTimeToComplete { get; private set; }
        public int CpuTimeToComplete { get; private set; }

        

        public DatabaseOperation(Transaction transaction, DatabaseOperationType operationType, int objectID, int ioTimeToComplete, int cpuTimeToComplete)
        {
            this.OperationID = OperationIDCounter++;
            this.Transaction = transaction;
            this.OperationType = operationType;
            this.ObjectID = objectID;

            this.IoTimeToComplete = ioTimeToComplete;
            this.CpuTimeToComplete = cpuTimeToComplete;
        }

        public void IncreaseIoTime()
        {
            this.ElapsedIoTime++;
        }

        public void IncreaseCpuTime()
        {
            this.ElapsedCpuTime++;
        }

        public void IncreaseBlockedOnTransactionTime()
        {
            this.ElapsedBlockedOnTransactionTime++;
        }

        public void IncreaseBlockedOnTransactionTime2()
        {
            this.ElapsedBlockedOnTransactionTime2++;
        }

        public void IncreaseBlockedOnHardDriveTime()
        {
            this.ElapsedBlockedOnHardDriveTime++;
        }

        public void IncreaseBlockedOnCpuTime()
        {
            this.ElapsedBlockedOnCpuTime++;
        }

        public void MarkCompleate()
        {
            if (this.OperationType == DatabaseOperationType.Write && !this.TempCompleted)
            {
                throw new Exception("Write operations cannot be marked as Completed before they are marked as TempCompleted");
            }
            this.Completed = true;
        }

        public void MarkTempCompleted()
        {
            if (this.OperationType == DatabaseOperationType.Read)
            {
                throw new Exception("Reads cannot be marked as TempCompleted");
            }
            this.TempCompleted = true;
        }

        internal void IncreaseTempWriteTime()
        {
            this.ElapsedTempWriteTime++;
        }
    }

    public enum DatabaseOperationType
    {
        Read,
        Write
    }
}
